home *** CD-ROM | disk | FTP | other *** search
- /*
- * C code from the article
- * "An Incremental Angle Point in Polygon Test"
- * by Kevin Weiler, kjw@autodesk.com
- * in "Graphics Gems IV", Academic Press, 1994
- */
-
- #include "polygon.h"
-
- /* quadrant id's, incremental angles, accumulated angle values */
- typedef short quadrant_type;
-
- /* result value from point in polygon test */
- typedef enum pt_poly_relation {INSIDE, OUTSIDE} pt_poly_relation;
-
- /* determine the quadrant of a polygon point
- relative to the test point */
- #define quadrant(vertex, x, y) \
- ( (vertex->x > x) ? ((vertex->y > y) ? 0 : 3) : ( (vertex->y > y) ? 1 : 2) )
-
- /* determine x intercept of a polygon edge
- with a horizontal line at the y value of the test point */
- #define x_intercept(pt1, pt2, yy) \
- (pt2->x - ( (pt2->y - yy) * ((pt1->x - pt2->x) / (pt1->y - pt2->y)) ) )
-
- /* adjust delta */
- #define adjust_delta(delta, vertex, next_vertex, xx, yy) \
- switch (delta) { \
- /* make quadrant deltas wrap around */ \
- case 3: delta = -1; break; \
- case -3: delta = 1; break; \
- /* check if went around point cw or ccw */ \
- case 2: case -2: if (x_intercept(vertex, next_vertex, yy) > xx) \
- delta = - (delta); \
- break; \
- }
-
- /* determine if a test point is inside of or outside of a polygon */
- /* polygon is "poly", test point is at "x","y" */
- pt_poly_relation
- point_in_poly(polygon_ptr poly, double x, double y)
- {
- vertex_ptr vertex, first_vertex, next_vertex;
- quadrant_type quad, next_quad, delta, angle;
-
- /* initialize */
- vertex = NULL; /* because polygon_get_vertex is a macro */
- vertex = first_vertex = polygon_get_vertex(poly,vertex);
- quad = quadrant(vertex, x, y);
- angle = 0;
- /* loop on all vertices of polygon */
- do {
- next_vertex = polygon_get_vertex(poly,vertex);
- /* calculate quadrant and delta from last quadrant */
- next_quad = quadrant(next_vertex, x, y);
- delta = next_quad - quad;
- adjust_delta(delta,vertex,next_vertex,x,y);
- /* add delta to total angle sum */
- angle = angle + delta;
- /* increment for next step */
- quad = next_quad;
- vertex = next_vertex;
- } while (vertex != first_vertex);
-
- /* complete 360 degrees (angle of + 4 or -4 ) means inside */
- if ((angle == +4) || (angle == -4)) return INSIDE; else return OUTSIDE;
-
- /* odd number of windings rule */
- /* if (angle & 4) return INSIDE; else return OUTSIDE; */
- /* non-zero winding rule */
- /* if (angle != 0) return INSIDE; else return OUTSIDE; */
- }
-